package org.ccay.vfs;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;

import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.Selectors;
import org.ccay.core.io.FileStoreType;
import org.ccay.core.io.VFSFileObject;
import org.springframework.util.Assert;

/**
 * apache commons-vfs2 虚拟文件对象实现
 * @author chaowangbang
 *
 */
public class ApacheVFSFileObject implements VFSFileObject {

	private FileObject fileObject;
	
	private String displayName;
	
	private String module;
	
	private String relativePath;
	
	private FileStoreType fileStoreType;
	
	private boolean inline = false;
	
	
	public ApacheVFSFileObject(String module,String relativePath,FileStoreType fileStoreType){
		Assert.notNull(module);
		this.module = module;
		
		Assert.notNull(relativePath);
		this.relativePath = relativePath.startsWith("/") ? relativePath.substring(1) : relativePath;
		
		Assert.notNull(fileStoreType);
		this.fileStoreType = fileStoreType;
		
		fileObject = VFS.resolveFile(module,fileStoreType,relativePath,null,null);
	}
	
	public ApacheVFSFileObject(VFSFileObject fileObject,FileStoreType fileStoreType){
		this(fileObject.getModule(),fileObject.getRelativePath(),fileStoreType);
	}
	
	@Override
	public String getDisplayName() {
		return displayName == null ? getBaseName() : displayName;
	}

	@Override
	public String getBaseName() {
		return fileObject.getName().getBaseName();
	}

	@Override
	public String getModule() {
		return module;
	}
	@Override
	public String getRootURI() {
		switch (fileStoreType) {
		case WROK:
			return VFS.getWorkRootURI(module);
		case ARCHIVE:
			return VFS.getArchiveRootURI(module);
		case TEMP:
			return VFS.getTempRootURI(module);
		}
		return null;
	}

	@Override
	public String getLocalRootAbsolutePath(){
		switch (fileStoreType) {
		case WROK:
			return VFS.getWorkRootURI(module).substring(VFS.LOCAL_URL_PREFIX.length());
		default:
			throw new VFSException("NotLocalFileSystem","NotLocalFileSystem");
		}
	}
	
	@Override
	public String getLocalAbsolutePath(){
		switch (fileStoreType) {
		case WROK:
			return VFS.getWorkRootURI(module).substring(VFS.LOCAL_URL_PREFIX.length()) + "/" + relativePath;
		default:
			throw new VFSException("NotLocalFileSystem","NotLocalFileSystem");
		}
	}
	
	@Override
	public String getAbsolutePath() {
		return fileObject.getName().getPath();
	}

	@Override
	public String getRelativePath() {
		return relativePath;
	}

	@Override
	public String getExtension() {
		return fileObject.getName().getExtension();
	}

	@Override
	public String getScheme() {
		return fileObject.getName().getScheme();
	}

	@Override
	public String getURI() {
		return fileObject.getName().getURI();
	}

	@Override
	public boolean isFile(){
		try {
			return fileObject.isFile();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}
	
	@Override
	public boolean isFolder() {
		try {
			return fileObject.isFolder();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}
	

	@Override
	public long getSize() {
		try {
			return fileObject.getContent().getSize();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}

	@Override
	public Date getLastModifiedTime() {
		try {
			return new Date(fileObject.getContent().getLastModifiedTime());
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}
	
	@Override
	public String getContentType() {
		try {
			return fileObject.getContent().getContentInfo().getContentType();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}

	@Override
	public InputStream getInputStream() {
		try {
			return fileObject.getContent().getInputStream();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}

	@Override
	public OutputStream getOutputStream() {
		try {
			return fileObject.getContent().getOutputStream();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}

	@Override
	public void close() {
		try {
			fileObject.close();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}

	}

	@Override
	public FileStoreType getStoreType() {
		return fileStoreType;
	}

	@Override
	public boolean exists() {
		try {
			return fileObject.exists();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}

	public void setDisplayName(String displayName) {
		this.displayName = displayName;
	}

	public boolean isInline() {
		return inline;
	}

	public void setInline(boolean inline) {
		this.inline = inline;
	}


	@Override
	public VFSFileObject copyToArchive() {
		return copyTo(FileStoreType.ARCHIVE);
	}


	@Override
	public VFSFileObject copyToWork() {
		return copyTo(FileStoreType.WROK);
	}


	@Override
	public VFSFileObject copyToTemp() {
		return copyTo(FileStoreType.TEMP);
	}
	

	private VFSFileObject copyTo(FileStoreType targetStoreType){
		if(targetStoreType == fileStoreType){
			return this;
		}
		try {
			ApacheVFSFileObject archive = new ApacheVFSFileObject(this,targetStoreType);
			archive.getFileObject().copyFrom(this.fileObject, Selectors.SELECT_ALL);
			return archive;
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}

	public FileObject getFileObject() {
		return fileObject;
	}

	@Override
	public boolean delete() {
		try {
			return fileObject.delete();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}

	@Override
	public int deleteAll() {
		try {
			return fileObject.deleteAll();
		} catch (FileSystemException e) {
			throw new VFSException(e.getCode(),e.getMessage(),e);
		}
	}

	@Override
	public String toString() {
		return "ApacheVFSFileObject [fileObject=" + fileObject + ", module=" + module + ", relativePath=" + relativePath + "]";
	}
}
